package com.wutianyi.session;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.UUID;

import javax.servlet.http.HttpSession;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;

import com.jolbox.bonecp.BoneCP;
import com.jolbox.bonecp.BoneCPConfig;
import com.wutianyi.web.wrapper.MyHttpSession;

public class DBSessionFactory extends AbstractSessionFactory {

	private static BoneCP connectionPool = null;
	private static final String updateSql = "INSERT INTO session_info (sessionid, info) VALUES(?,?) ON DUPLICATE KEY UPDATE info = VALUES(info)";
	private static final String fetchSql = "SELECT info FROM session_info WHERE sessionid=?";
	static {
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		BoneCPConfig config = new BoneCPConfig();
		config.setJdbcUrl("jdbc:mysql://localhost:3307/test");
		config.setUsername("root");
		config.setPassword("860728");
		config.setMinConnectionsPerPartition(5);
		config.setMaxConnectionsPerPartition(10);
		config.setPartitionCount(1);
		try {
			connectionPool = new BoneCP(config);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	protected HttpSession createHttpSession(String sessionId) {
		HttpSession httpSession = null;
		if (StringUtils.isNotBlank(sessionId)) {
			try {
				Connection conn = connectionPool.getConnection();
				PreparedStatement psmt = conn.prepareStatement(fetchSql);
				psmt.setString(1, sessionId);
				ResultSet rs = psmt.executeQuery();
				String info = null;
				if (rs.next()) {
					info = rs.getString("info");
				}
				if (StringUtils.isNotBlank(info)) {
					ByteArrayInputStream bais = new ByteArrayInputStream(
							info.getBytes("ISO-8859-1"));
					ObjectInputStream ois = new ObjectInputStream(bais);
					httpSession = (HttpSession) ois.readObject();
				}
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (null == httpSession) {
			httpSession = new MyHttpSession(UUID.randomUUID().toString());
		}
		return httpSession;
	}

	@Override
	public void saveSession(HttpSession httpSession) {
		if (null == httpSession
				|| httpSession.getLastAccessedTime() == httpSession
						.getCreationTime()) {
			return;
		}
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try {
			ObjectOutputStream oos = new ObjectOutputStream(baos);
			oos.writeObject(httpSession);
			String info = new String(baos.toByteArray(), "ISO-8859-1");
			Connection conn = connectionPool.getConnection();
			PreparedStatement psmt = conn.prepareStatement(updateSql);
			psmt.setString(1, httpSession.getId());
			psmt.setString(2, info);

			psmt.executeUpdate();
			conn.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		SessionFactory sessionFactory = new DBSessionFactory();
		HttpSession httpSession = sessionFactory.getHttpSession(null);
		System.out.println(httpSession.getId());
		System.out.println(httpSession.getCreationTime());
		System.out.println(httpSession.getLastAccessedTime());
		for (int i = 0; i < 10; i++) {
			httpSession.setAttribute(RandomStringUtils.randomNumeric(10),
					RandomStringUtils.randomAscii(50));
		}

		sessionFactory.saveSession(httpSession);

		httpSession = sessionFactory.getHttpSession(httpSession.getId());
		System.out.println("fetch from db.. ...");
		System.out.println(httpSession.getId());
		System.out.println(httpSession.getCreationTime());
		System.out.println(httpSession.getLastAccessedTime());
		Enumeration<String> keys = httpSession.getAttributeNames();
		while (keys.hasMoreElements()) {
			String k = keys.nextElement();
			System.out.println(k + ": " + httpSession.getAttribute(k));
		}
	}

}
